package com.ruoyi.socket.probuffer;

import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.group.ChannelGroup;
import io.netty.channel.group.DefaultChannelGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.protobuf.ProtobufDecoder;
import io.netty.handler.codec.protobuf.ProtobufEncoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32FrameDecoder;
import io.netty.handler.codec.protobuf.ProtobufVarint32LengthFieldPrepender;
import io.netty.util.concurrent.GlobalEventExecutor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/***
 *  @description
 *  @author zhao
 *  @date: 2020/6/8
 *  @version: v1.0
 */
public class ProtoChannelHandler extends ChannelInitializer<SocketChannel> {

    private static Logger logger = LoggerFactory.getLogger(ProtoServerHandler.class);

    //保留所有与服务器建立连接的channel对象
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);


    @Override
    protected void initChannel(SocketChannel nioServerSocketChannel) throws Exception {

//        nioServerSocketChannel.read().


        logger.info("initChannel id{}",nioServerSocketChannel.id());
        // 通过pip添加各种处理器

        ChannelPipeline pipeline = nioServerSocketChannel.pipeline();
        //解码器，通过Google Protocol Buffers序列化框架动态的切割接收到的ByteBuf
        // c处理半包消息
        // ProtobufVarint32FrameDecoder：用于decode前解决半包和粘包问题（利用包头中的包含数组长度来识别半包粘包）
        // 解码(处理半包)
        pipeline.addLast(new ProtobufVarint32FrameDecoder());
//        pipeline.addLast(new ObjectDecoder());

        //服务器端接收的是 客户端pb对象，所以这边将接收对象进行解码生产实列
        pipeline.addLast(new ProtobufDecoder(DataInfo.DeviceData.getDefaultInstance()));
        //Google Protocol Buffers编码器
        // ProtobufVarint32LengthFieldPrepender：用于在序列化的字节数组前加上一个简单的包头，只包含序列化的字节长度。
        // /加长度
        pipeline.addLast(new ProtobufVarint32LengthFieldPrepender());

        //
        //Google Protocol Buffers编码器
        // ProtobufEncoder：用于对Probuf类型序列化。
        pipeline.addLast(new ProtobufEncoder());
//        pipeline.addLast(new ObjectEncoder());

        pipeline.addLast(new ProtoServerHandler());

    }


    //表示服务端与客户端连接建立
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();  //其实相当于一个connection
//         * 调用channelGroup的writeAndFlush其实就相当于channelGroup中的每个channel都writeAndFlush
//         * 先去广播，再将自己加入到channelGroup中
        System.out.println("remoteAddress..." + channel.remoteAddress());
        channelGroup.add(channel);
    }


    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {
        //验证一下每次客户端断开连接，连接自动地从channelGroup中删除调。
        //当客户端和服务端断开连接的时候，下面的那段代码netty会自动调用，所以不需要人为的去调用它
        //channelGroup.remove(channel);
        System.out.println(channelGroup.size());
    }

}
